package com.mytx.sso.controller;

import com.alibaba.fastjson.JSONObject;
import com.mytx.common.constant.Constant;
import com.mytx.common.pojo.CommonResult;
import com.mytx.common.utils.IDUtils;
import com.mytx.mapper.ContactMapper;
import com.mytx.mapper.UserMapper;
import com.mytx.pojo.Contact;
import com.mytx.pojo.Message;
import com.mytx.pojo.User;
import com.mytx.pojo.UserExample;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@RestController
public class ContactController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ContactMapper contactMapper;

    @Autowired
    private UserMapper userMapper;


    @Autowired
    private HttpServletRequest request;

    /**
     * 拒绝添加为好友
     *
     * @return
     */
    @RequestMapping(value = "/refuseAddContact", method = RequestMethod.POST)
    public CommonResult refuseAddContact(@RequestBody Contact contact) {
        String uId = request.getHeader("uId");
        User user = getUser(uId);

        String targetUserId = contact.gettId();
        contact.setmId(targetUserId);
        contact.settId(uId);
        //把状态设置为0 ，表示拒绝,更新到redis
        contact.setStatus(Constant.INVITE_STATUS_REFUSE);
        redisTemplate.opsForValue().set(Constant.ADD_CONTACT + targetUserId + ":" + uId, contact, 5, TimeUnit.DAYS);
        List<String> userIdList = new ArrayList<>();
        userIdList.add(targetUserId);
        Message notify = new Message();
        notify.setType(Constant.PUSH_MESSAGE_REFUSE_ADD_CONTACT);
        notify.setFromId(uId);
        notify.setNick(user.getNick());
        notify.setAvatar(user.getAvatar());
        notify.setCreated(new Date());
        pushMessage(userIdList, notify);
        return CommonResult.ok();
    }

    /**
     * 更新联系人
     *
     * @param contact
     * @return
     */
    @RequestMapping(value = "/updateContact", method = RequestMethod.POST)
    public CommonResult updateContact(@RequestBody Contact contact) {
        //获取当前登录的用户id
        String uId = request.getHeader("uId");

        String targetUserId = contact.gettId();

        //获取当前联系人关系的权限信息
        String authorityTLocation = contact.gettLocation();
        String authorityTRelationInfinite = contact.gettRelationInfinite();
        String authorityLocation = contact.getLocation();
        String authoryityRelationInfinite = contact.getRelationInfinite();
        String authority_group_name = contact.getGroupName();
        //判断是否有修改信息
        if ((StringUtils.isNotBlank(authorityTLocation) || StringUtils.isNotBlank(authorityTRelationInfinite) ||
                StringUtils.isNotBlank(authorityLocation) || StringUtils.isNotBlank(authoryityRelationInfinite) ||
                StringUtils.isNotBlank(authority_group_name))) {            //根据cid查询出联系人关系对象
            Contact targetContact = contactMapper.selectContactByCid(contact.getcId());
            //判断当前登录用户是否在tid
            if (StringUtils.equals(uId, targetContact.gettId())) {
                //如果在tid里面
                targetContact.settGroupName(contact.getGroupName());
            } else {
                //如果在mid里面
                targetContact.setGroupName(contact.getGroupName());
            }
            targetContact.setLocation(authorityLocation);
            targetContact.setRelationInfinite(authoryityRelationInfinite);
            targetContact.settLocation(authorityTLocation);
            targetContact.settRelationInfinite(authorityTRelationInfinite);
            int result = contactMapper.updateByPrimaryKeySelective(targetContact);
            if (result == 1) {
                //判断好友关系是否为单边联系人关系
                if (StringUtils.equals(targetContact.getStatus(), Constant.CONTACT_STATUS_MDELETE) || StringUtils.equals(targetContact.getStatus(), Constant.CONTACT_STATUS_TDELETE)) {
                    //如果为单边联系人关系,只修改权限信息,不展示权限到前端
                    return CommonResult.ok();
                }
                //将修改后的权限通知给对方用户进行展示
                targetContact.setLocation(authorityLocation);
                targetContact.setRelationInfinite(authoryityRelationInfinite);
                targetContact.settLocation(authorityTLocation);
                targetContact.settRelationInfinite(authorityTRelationInfinite);
                List<String> userIdList = new ArrayList<>();
                userIdList.add(contact.gettId());
                Message notify = new Message();
                notify.setType(Constant.PUSH_MESSAGE_CONTACT_INFO_CHANGE);
                notify.setExtraData(targetContact);
                pushMessage(userIdList, notify);
            }
        }
        return CommonResult.ok();
    }

    /**
     * 删除联系人
     *
     * @param contact
     * @return
     */
    @RequestMapping(value = "/deleteContact", method = RequestMethod.POST)
    public CommonResult deleteContact(@RequestBody Contact contact) {
        String uId = request.getHeader("uId");
        logger.info("删除联系人：" + uId);
        Contact contactTable = contactMapper.selectByPrimaryKey(contact.getcId());
        //获取在表中联系人关系的状态
        String status = contactTable.getStatus();
        //判断双方联系人的关系是是否已经删除了
        if (StringUtils.equals(Constant.CONTACT_STATUS_DELETE, status)) {
            //如果双方联系人的关系已经删除了,就直接提示信息给客户端
            return CommonResult.build(Constant.DELETE_CONTACT_ERROR, "你们已经不是好友了,无需再删除");
        }
        //如果好友没有删除,判断是正常的好友关系
        if (StringUtils.equals(Constant.CONTACT_STATUS_MUTUAL, status)) {
            //如果是正常的好友关系，那么是单边删除
            //判断主动删除的人在tid，还是在mid
            List<String> userIdList = new ArrayList<>();
            if (uId.equals(contactTable.getmId())) {
                //将好友关系状态设置为1
                contactTable.setStatus(Constant.CONTACT_STATUS_MDELETE);
                //不给对方联系人权限
                contactTable.settLocation(Constant.CONTACT_NO_LOCATIION);
                contactTable.settRelationInfinite(Constant.CONTACT_NO_RELATION_INFINITE);
                contactMapper.updateByPrimaryKeySelective(contactTable);
                //给tid用户推送删除消息
                userIdList.add(contactTable.gettId());
                contactTable.settId(null);
            } else if (uId.equals(contactTable.gettId())) {
                //不给对方联系人权限
                contactTable.setLocation(Constant.CONTACT_NO_LOCATIION);
                contactTable.setRelationInfinite(Constant.CONTACT_NO_RELATION_INFINITE);
                //将好友关系设置为2
                contactTable.setStatus(Constant.CONTACT_STATUS_TDELETE);
                contactMapper.updateByPrimaryKeySelective(contactTable);
                //给mid推送消息
                userIdList.add(contactTable.getmId());
                contactTable.settId(null);
            }
            //给对方联系人推送一条数据
            Message notify = new Message();
            notify.setFromId(uId);//不能去掉，app 端会用到
            notify.setType(Constant.PUSH_MESSAGE_DELETE_CONTACT);
            notify.setExtraData(contactTable);
            notify.setCreated(new Date());
            pushMessage(userIdList, notify);
            return CommonResult.ok();
        }
        //如果已经不是正常的好友关系，那么直接将状态修改为3
        //设置双方都没有彼此的权限
        contactTable.setLocation(Constant.CONTACT_NO_LOCATIION);
        contactTable.setRelationInfinite(Constant.CONTACT_NO_RELATION_INFINITE);
        contactTable.settLocation(Constant.CONTACT_NO_LOCATIION);
        contactTable.settRelationInfinite(Constant.CONTACT_NO_RELATION_INFINITE);
        //将好友关系状态设置为3
        contactTable.setStatus(Constant.CONTACT_STATUS_DELETE);
        //修改到数据库当中
        contactMapper.updateByPrimaryKeySelective(contactTable);
        return CommonResult.ok();
    }


    /**
     * 根据手机号码查询用户信息
     *
     * @param mobile
     * @return
     */
    @PostMapping("/searchContact")
    public CommonResult searchContact(@RequestBody String mobile) {
        logger.info("searchContact:" + mobile);
        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria();
        criteria.andPhoneEqualTo(mobile);
        List<User> tbUsers = userMapper.selectByExample(userExample);
        if (tbUsers.size() == 0) {
            return CommonResult.build(Constant.MOBILE_INVALID, "没有该手机号对应的用户");
        }
        User user = tbUsers.get(0);
        user.setPassword(null);
        user.setPayPassword(null);
        user.setPayLimit(null);
        user.setCreated(null);
        user.setUpdated(null);
        return CommonResult.ok(user);
    }

    /**
     * 请求添加好友
     *
     * @param contact
     * @return
     */
    @RequestMapping(value = "/sendInviteMessage", method = RequestMethod.POST)
    public CommonResult sendInviteMessage(@RequestBody Contact contact) {
        String uId = request.getHeader("uId");
        logger.info("sendInviteMessage uid:{}", uId);
        contact.setStatus(Constant.CONTACT_STATUS_MUTUAL);
        String targetUserId = contact.gettId();
        List<String> userIdList = new ArrayList<>();
        userIdList.add(targetUserId);
        //先检查redis中是否保存有我发送给对方的添加联系人请求信息，
        Object contactObject = redisTemplate.opsForValue().get(Constant.ADD_CONTACT + uId + ":" + targetUserId);
        if (contactObject != null) {
            Contact contact1 = (Contact) contactObject;
            //如果保存的信息的状态是已经被拒绝，则返回请求方，需要等这条信息过期后，才能再次发起请求，过期时间目前设置的是 5天
            if (contact1.getStatus().equals(Constant.INVITE_STATUS_REFUSE)) {
                return CommonResult.build(Constant.REFUSE_ADD_CONTACT, "好友请求已经被拒绝，还不能重新发起请求", redisTemplate.getExpire("ADD_CONTACT:" + uId + ":" + targetUserId, TimeUnit.DAYS) + "");
            }
        }

        //查mysql,我们是否是单边联系人状态，如果只是我删除对方，对方并没有删除我，那无须通知对方，直接更新双方联系人状态，并push 消息到对方，更新联系人状态
        //如果已经是好友，则不执行下面的代码,返回一条异常信息返回给客户端
        Contact oldTargetContact = contactMapper.selectUnilateralByMIDTID(uId, targetUserId);
        if (oldTargetContact != null) {
            //判断联系人的关系是否为单边联系人关系
            if (StringUtils.equals(oldTargetContact.getStatus(), Constant.CONTACT_STATUS_MDELETE)) {
                oldTargetContact.setGroupName(contact.getGroupName());
                oldTargetContact.settLocation(contact.gettLocation());
                oldTargetContact.settRelationInfinite(contact.gettRelationInfinite());
            } else if (StringUtils.equals(oldTargetContact.getStatus(), Constant.CONTACT_STATUS_TDELETE)) {
                oldTargetContact.settGroupName(contact.getGroupName());
                oldTargetContact.setLocation(contact.gettLocation());
                oldTargetContact.setRelationInfinite(contact.gettRelationInfinite());
            }//是单边联系人关系
            oldTargetContact.setStatus(Constant.CONTACT_STATUS_MUTUAL);
            contactMapper.updateByPrimaryKeySelective(oldTargetContact);
            //通知对方，联系人信息变动
            Message notify = new Message();
            notify.setType(Constant.PUSH_MESSAGE_CONTACT_INFO_CHANGE);
            notify.setExtraData(oldTargetContact);
            pushMessage(userIdList, notify);
            //contact.settCid(oldTargetContact.getcId());//补全 tCid
            //向主动添加方返回一条被动添加放的数据
            Contact newContact = oldTargetContact;
            User targetUser = getUser(targetUserId);
            newContact.setTargetUser(targetUser);
            return CommonResult.ok(newContact);
        }
        //补全contact 信息
        contact.setmId(uId);
        contact.setCreated(new Date());
        //保存邀请信息到redis，并设置过期时间，
        redisTemplate.opsForValue().set(Constant.ADD_CONTACT + uId + ":" + targetUserId, contact, 5, TimeUnit.DAYS);
        User user = getUser(uId);

        //通知消息给客户端
        Message notify = new Message();
        notify.setFromId(uId);
        notify.setNick(user.getUsername());
        notify.setAvatar(user.getAvatar());
        notify.setType(Constant.PUSH_MESSAGE_REQUEST_ADD_CONTACT);
        notify.setVisible(Constant.MESSAGE_VISIBLE);
        notify.setContent(contact.getInviteMessage());
        notify.setCreated(new Date());
        pushMessage(userIdList, notify);
        return CommonResult.ok();
    }

    /**
     * 同意添加为好友
     *
     * @param contact
     * @return
     */
    @RequestMapping(value = "/addContact", method = RequestMethod.POST)
    public CommonResult addContact(@RequestBody Contact contact) {


        String uId = request.getHeader("uId");
        //获取好友请求添加方
        String targetUserId = contact.gettId();

        //查询redis 获取对方发送邀请时候保存的Contact信息，并检查是否为空，如果为空，说明已经过期，目前处理是new 一个Contact信息
        Object contactObject = redisTemplate.opsForValue().get(Constant.ADD_CONTACT + contact.gettId() + ":" + uId);
        Contact targetContact;
        if (contactObject != null) {
            targetContact = (Contact) contactObject;
            //添加好友后，清理redis中互相的请求信息
            redisTemplate.delete(Constant.ADD_CONTACT + targetUserId + ":" + uId);
            redisTemplate.delete(Constant.ADD_CONTACT + uId + ":" + targetUserId);
        } else {//redis 中找不到对方发送邀请时候的保存的Contact 信息了，5天有效期，说明是我接受请求是在对方发起添加好友请求的5天后，那就new 一个 Contact
            targetContact = new Contact(targetUserId, uId, Constant.CONTACT_STATUS_MUTUAL, new Date());
        }

        //设置双方给到对方的 查看轨迹和查询定位的权限
        targetContact.setLocation(contact.gettLocation());
        targetContact.setRelationInfinite(contact.gettRelationInfinite());
        //查数据库，检查曾经是否是联系人关系
        Contact contactTable = contactMapper.selectContactByStatus(uId, contact.gettId());
        if (contactTable != null) {
            String status = contactTable.getStatus();
            if (!StringUtils.equals(status, Constant.CONTACT_STATUS_MUTUAL)) {//说明曾经是联系人关系
//            String cid = contactTable.getcId();
//            contact.setcId(cid);
                Date date = new Date();
                contactTable.setUpdated(date);
                //将状态设置为正常的状态
                //判断当前用户在数据库中的位置来将前端的数据映射到数据库中
                if (StringUtils.equals(uId, contactTable.gettId())) {
                    contactTable.setGroupName(targetContact.getGroupName());
                    contactTable.settGroupName(contact.getGroupName());
                    contactTable.settLocation(targetContact.gettLocation());
                    contactTable.settRelationInfinite(targetContact.gettRelationInfinite());
                    contactTable.setLocation(contact.gettLocation());
                    contactTable.setRelationInfinite(contact.gettRelationInfinite());
                } else {
                    contactTable.settGroupName(targetContact.getGroupName());
                    contactTable.setGroupName(contact.getGroupName());
                    contactTable.setLocation(targetContact.gettLocation());
                    contactTable.setRelationInfinite(targetContact.gettRelationInfinite());
                    contactTable.settLocation(contact.gettLocation());
                    contactTable.settRelationInfinite(contact.gettRelationInfinite());
                }
                contactTable.setStatus(Constant.CONTACT_STATUS_MUTUAL);
                String groupName = contactTable.getGroupName();
                String tGroupName = contactTable.gettGroupName();
                // TODO: 2018/4/16 0016  应该写个sql命令，一次更新多条
                String tid = contactTable.gettId();
                contactMapper.updateByPrimaryKeySelective(contactTable);
                Contact newContact = contactTable;
                User user = getUser(uId);
                user.setBalance(null);//清空我的余额信息
                contactTable.settId(null);
                contactTable.setTargetUser(user);
                List<String> userIdList = new ArrayList<>();
                userIdList.add(targetUserId);
                //给主动添加方推送条消息
                if (!StringUtils.equals(uId, tid)) {
                    contactTable.setGroupName(tGroupName);
                } else {
                    contactTable.setGroupName(groupName);
                }
                Message notify = new Message();
                notify.setType(Constant.PUSH_MESSAGE_ACCEPT_ADD_FRIEND);
                notify.setVisible(Constant.MESSAGE_VISIBLE);
                notify.setExtraData(contactTable);
                notify.setCreated(new Date());
                pushMessage(userIdList, notify);
                User targetUser = getUser(targetUserId);
                newContact.setTargetUser(targetUser);
                //将修改后的数据库中的数据返回给客户段进行处理
                //将后端的的权限数据信息映射到前端去进行展示
//                   newContact.settId(tid);
                if (!StringUtils.equals(uId, tid)) {
                    newContact.setGroupName(groupName);
                } else {
                    newContact.setGroupName(tGroupName);
                }
                return CommonResult.ok(newContact);
            }
        } else {
            //曾经不是联系人关系，插入一条新的联系人信息
            targetContact.setcId(IDUtils.genUUID());
            targetContact.settGroupName(contact.getGroupName());
            contactMapper.insertSelective(targetContact);
        }
        User user = getUser(uId);
        user.setBalance(null);//清空我的余额信息
        targetContact.settId(null);
        targetContact.setTargetUser(user);
        List<String> userIdList = new ArrayList<>();
        userIdList.add(contact.gettId());
        //在前端展示的时候，将location与tLocation交换
        //给主动添加方推送条消息
        Message notify = new Message();
        notify.setType(Constant.PUSH_MESSAGE_ACCEPT_ADD_FRIEND);
        notify.setVisible(Constant.MESSAGE_VISIBLE);
        notify.setExtraData(targetContact);
        notify.setCreated(new Date());
        pushMessage(userIdList, notify);
        //返回一条对方的用户给被动添加方
        Contact newContact = targetContact;
        newContact.settId(targetUserId);
        newContact.setGroupName(targetContact.gettGroupName());
        User targetUser = getUser(targetUserId);
        newContact.setTargetUser(targetUser);
        return CommonResult.ok(newContact);
    }


    /**
     * 发起位置请求
     *
     * @param contact
     * @return
     */
    @RequestMapping(value = "/location", method = RequestMethod.POST)
    public CommonResult location(@RequestBody Contact contact) {
        String uId = request.getHeader("uId");
        logger.info("定位请求：", contact);
        //获取到被发起位置请求的用户id
        String targetUserId = contact.gettId();
        //通过查看数据库，检查是否有权限查看对方的位置信息，如果这儿不检查数据库，还不如直接从客户端向对方发起请求，
        //以后再根据安全的角度，看是否可以直接从客户端向对方发起位置请求
        Contact targetContact = contactMapper.selectByPrimaryKey(contact.getcId());
        //判断查询用户id在mid还是在tid里面
        if (StringUtils.equals(uId, targetContact.getmId())) {
            //如果在mid里面那么判断tLocation是否为1
            if (!StringUtils.equals(targetContact.getLocation(), Constant.LOCATION_AUTHORITY)) {
                return CommonResult.build(Constant.NO_AUTHORITY, "没有权限查看对方位置信息");
            }

        } else if (StringUtils.equals(uId, targetContact.gettId())) {
            //如果在tid里面那么判断Location是否为1
            if (!StringUtils.equals(targetContact.gettLocation(), Constant.LOCATION_AUTHORITY)) {
                return CommonResult.build(Constant.NO_AUTHORITY, "没有权限查看对方位置信息");
            }
        }
        //如果有权限直接推送消息给用户
        //contact.setlId(myUser.getuId());
        List<String> userIdList = new ArrayList<>();
        Message notify = new Message();
        notify.setType(Constant.PUSH_MESSAGE_REQUEST_QUERY_LOCATION);
        notify.setExtraData(targetContact);
        userIdList.add(targetUserId);
        notify.setCreated(new Date());
        pushMessage(userIdList, notify);
        return CommonResult.ok();
    }

    @RequestMapping(value = "/connectInfinite", method = RequestMethod.POST)
    public CommonResult connectInfinite(@RequestBody JSONObject body) {
        //互联暗号
        String connectKey = body.getString("connectKey");
        Contact contact = body.getObject("contact", Contact.class);
        String userId = contact.gettId();
        //每次只查询两级关联的联系人，即对方的和“对方的对方的”
        //查询对方的具有相同  “互联暗号”的联系人  1级
        List<Contact> contacts = contactMapper.queryConnectInfiniteContacts(userId, connectKey);
        if (contacts == null || contacts.size() == 0) {
            return CommonResult.build(Constant.HAVE_NOT_MORE_CHILD_CONTACT, "没有更多子联系人了");
        }
        for (Contact connectInfiniteContact : contacts) {
            //查询对方的对方的（2级）具有相同  “互联暗号”的联系人
            List<Contact> childContacts = contactMapper.queryConnectInfiniteContacts(connectInfiniteContact.getTargetUser().getuId(), connectKey);
            if (childContacts == null || childContacts.size() == 0) {
                connectInfiniteContact.setHaveMoreChildContact(false);
            } else {
                connectInfiniteContact.setChildContactList(childContacts);
            }
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("contacts", contacts);
        return CommonResult.ok(resultMap);
    }


    @RequestMapping(value = "/refreshConnectInfinite", method = RequestMethod.POST)
    public CommonResult refreshConnectInfinite(@RequestBody Contact contact) {

        // TODO: 2018/5/17 0017 应该要检查该用户是否有权限做联系人的变更
        Contact otherContact = new Contact();
//        otherContact.setcId(contact.gettCid());
        otherContact.settId(contact.getmId());
        List<Contact> contacts = new ArrayList<>();
        contacts.add(contact);
        contacts.add(otherContact);
        // TODO: 2018/5/17 0017 应该写一个批量更新，以后再写
        contactMapper.updateByPrimaryKeySelective(contact);
        contactMapper.updateByPrimaryKeySelective(otherContact);


        return CommonResult.ok();
    }


    /**
     * 根据用户id查询对应的用户信息
     *
     * @param uId
     * @return
     */
    private User getUser(String uId) {
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(Constant.USER_SESSION + uId);
        if(entries.isEmpty()){
            return  userMapper.selectByPrimaryKey(uId);
        }
        return JSONObject.parseObject(JSONObject.toJSONString(entries), User.class);
    }

    /**
     * 确保数据完整，不然插入到数据库要报错
     *
     * @param contact
     */
    private void checkData(Contact contact) {
        //infinite_tag,infinite_key,
        //        infinite_chat, up_chat, adjust_structure
        if (contact.getLocation() == null) {
            contact.setLocation("0");
        }
        if (contact.gettLocation() == null) {
            contact.settLocation("0");
        }

        if (contact.getRelationInfinite() == null) {
            contact.setRelationInfinite("0");
        }
        if (contact.gettRelationInfinite() == null) {
            contact.settRelationInfinite("0");
        }
        if (contact.getInfiniteTag() == null) {
            contact.setInfiniteTag("0");
        }
        if (contact.getInfiniteKey() == null) {
            contact.setInfiniteKey("0");
        }
        if (contact.getInfiniteChat() == null) {
            contact.setInfiniteChat("0");
        }
        if (contact.getUpChat() == null) {
            contact.setUpChat("0");
        }
        if (contact.getAdjustStructure() == null) {
            contact.setAdjustStructure("0");
        }
    }

    private void pushMessage(List<String> userIdList, Message notify) {
        JSONObject info = new JSONObject();
        info.put("userIdList",userIdList);
        info.put("message",notify);
        redisTemplate.convertAndSend(Constant.NOTIFY_PUSH_MESSAGE,info );
    }

}
